package cn.geodata.dataview.action;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.apache.commons.io.IOUtils;
import org.apache.log4j.Logger;
import org.apache.xalan.processor.TransformerFactoryImpl;
import org.apache.xerces.jaxp.DocumentBuilderFactoryImpl;
import org.geotools.feature.Feature;
import org.geotools.feature.FeatureCollection;
import org.geotools.feature.FeatureIterator;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.xml.sax.SAXException;

import cn.geodata.dataview.util.Util;

import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.MultiPolygon;

public class PositionKML {
	private static Logger Log = Logger.getLogger(PositionGML.class);
	
	private ArrayList<int[]> pathRow;
	private FeatureCollection fs;
	private static String KML_NAMESPACE = "http://earth.google.com/kml/2.1";
	private InputStream stream;
	
	public InputStream getKml() throws IOException, SAXException, TransformerException, URISyntaxException, ParserConfigurationException{
//		System.out.println(IOUtils.toString(this.stream));
		return this.stream;
	}
	
	private Element[] createStyleList(Document doc){
		Map<String, String> _styles = new HashMap<String, String>();
		_styles.put("style.0", "FF0000FF");
		_styles.put("style.1", "DD0000FF");
		_styles.put("style.2", "BB0000FF");
		_styles.put("style.3", "990000FF");
		_styles.put("style.4", "770000FF");
		
		ArrayList<Element> _list = new ArrayList<Element>(_styles.size());
		for(String _key : _styles.keySet()){
			Element _style = doc.createElementNS(KML_NAMESPACE, "Style");
			_style.setAttribute("id", _key);
			
			Element _line = doc.createElementNS(KML_NAMESPACE, "LineStyle");
			_style.appendChild(_line);
			
			Element _color = doc.createElementNS(KML_NAMESPACE, "color");
			_color.setTextContent(_styles.get(_key));
			_line.appendChild(_color);
			
			Element _width = doc.createElementNS(KML_NAMESPACE, "width");
			_width.setTextContent("1");
			_line.appendChild(_width);
			
			_list.add(_style);
		}
		
		return (Element[])_list.toArray(new Element[0]);
	}
	
	private Element[] createPlaceMark(Document doc){
		ArrayList<Element> _list = new ArrayList<Element>();
		
		FeatureIterator _it = this.fs.features();
		while(_it.hasNext()){
			Feature _f = _it.next();
			
			Element _place = doc.createElementNS(KML_NAMESPACE, "Placemark");
			
			Element _name = doc.createElementNS(KML_NAMESPACE, "name");
			_name.setTextContent("test");
			_place.appendChild(_name);
			
			Element _style = doc.createElementNS(KML_NAMESPACE, "styleUrl");
			_style.setTextContent("#style." + 2);
			_place.appendChild(_style);
			
			Element _line = doc.createElementNS(KML_NAMESPACE, "LineString");
			_place.appendChild(_line);
			
			Element _altitudeMode = doc.createElementNS(KML_NAMESPACE, "altitudeMode");
			_altitudeMode.setTextContent("absolute");
			_line.appendChild(_altitudeMode);
			
			StringBuffer _text = new StringBuffer();
			MultiPolygon _multiPolygon = (MultiPolygon)_f.getDefaultGeometry();
			for(Coordinate _c : _multiPolygon.getCoordinates()){
				_text.append(_c.x + "," + _c.y + "," + 0 + " ");
			}
			
			Element _coordinates = doc.createElementNS(KML_NAMESPACE, "coordinates");
			_coordinates.setTextContent(_text.toString());
			_line.appendChild(_coordinates);
			
			_list.add(_place);
		}
		return (Element[])_list.toArray(new Element[0]);
	}
	
	public void setPathRow(String[] prs) throws Exception {
		ArrayList<int[]> _pathRow = new ArrayList<int[]>();
		for(String pr : prs){
			String[] _parts = pr.trim().split(",");
			if(_parts.length != 2){
				throw new Exception("Path and row parameters are incorrect");
			}
			
			_pathRow.add(new int[]{Integer.parseInt(_parts[0]), Integer.parseInt(_parts[1])});
		}
		pathRow = _pathRow;
	}
	
	public String execute() throws Exception {
		if(this.pathRow == null){
			throw new NullPointerException("Not found avaliable path and row parameter");
		}
		this.fs = Util.locatePathRows(this.pathRow);
		
		try{
			Document _doc = DocumentBuilderFactoryImpl.newInstance().newDocumentBuilder().newDocument();
			Element _root = _doc.createElementNS(KML_NAMESPACE, "kml");
			_doc.appendChild(_root);
			
			Element _docu = _doc.createElementNS(KML_NAMESPACE, "Document");
			_root.appendChild(_docu);

			Element _name = _doc.createElementNS(KML_NAMESPACE, "name");
			_name.setTextContent("test");
			_docu.appendChild(_name);
			
			Element _desc = _doc.createElementNS(KML_NAMESPACE, "description");
			_desc.setTextContent("test");
			_docu.appendChild(_desc);
			
			for(Element _e : this.createStyleList(_doc)){
				_docu.appendChild(_e);
			}
			
			for(Element _e : this.createPlaceMark(_doc)){
				_docu.appendChild(_e);
			}
			
			ByteArrayOutputStream _outStream = new ByteArrayOutputStream();
			Transformer _transformer = TransformerFactoryImpl.newInstance().newTransformer();
			_transformer.setOutputProperty(OutputKeys.INDENT, "yes");
			_transformer.transform(new DOMSource(_doc), new StreamResult(_outStream));
			
			this.stream = new ByteArrayInputStream(_outStream.toByteArray());
		}
		catch(Exception err){
			Log.error(err);
			this.stream = new ByteArrayInputStream("<a></a>".getBytes());
		}

		return "success";
	}
}
